package com.treasure.mall.zbq.common;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.*;

/**
 * @author allan
 * @date 2018-05-10
 */
public class ObjectUtils {

    private static Logger logger = LoggerFactory.getLogger(ObjectUtils.class);

    /**
     * 描述 : <byte[]转Object>. <br>
     * <p>
     * <使用方法说明>
     * </p>
     *
     * @param bytes
     * @return
     */
    public static Object toObject(byte[] bytes) throws IOException, ClassNotFoundException {
        Object obj;
        ByteArrayInputStream bis = null;
        ObjectInputStream ois = null;
        try {
            bis = new ByteArrayInputStream(bytes);
            ois = new ObjectInputStream(bis);
            obj = ois.readObject();
        } finally {
            if (ois != null) {
                ois.close();
            }
            if (bis != null) {
                bis.close();
            }
        }
        return obj;
    }

    /**
     * 描述 : <Object转byte[]>. <br>
     * <p>
     * <使用方法说明>
     * </p>
     *
     * @param obj
     * @return
     */
    public static byte[] toByteArray(Object obj) throws IOException {
        byte[] bytes;
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        ObjectOutputStream oos = null;
        try {
            oos = new ObjectOutputStream(bos);
            oos.writeObject(obj);
            oos.flush();
            bytes = bos.toByteArray();
        } finally {
            if (oos != null) {
                oos.close();
            }
            bos.close();
        }
        return bytes;
    }

    /**
     * 判断对象是否为空（空列表，空字符串，空map）
     *
     * @param object
     * @return
     */
    public static boolean isEmpty(Object object) {
        if (object == null) {
            return true;
        }
        if (object instanceof String) {
            return stringIsEmpty((String) object);
        }
        if (object instanceof CharSequence) {
            return ((CharSequence) object).length() == 0;
        }
        if (object instanceof Collection) {
            return ((Collection) object).isEmpty();
        }
        if (object instanceof Map) {
            return ((Map) object).isEmpty();
        }
        if (object.getClass().isArray()) {
            return Array.getLength(object) == 0;
        }
        return false;
    }

    /**
     * 判断给定字符串是否空白串。
     * 空白串是指由空格、制表符、回车符、换行符组成的字符串
     * 若输入字符串为null或空字符串，返回true
     *
     * @param str
     * @return
     */
    private static boolean stringIsEmpty(String str) {
        if (str == null || str.length() == 0) {
            return true;
        }
        for (int i = 0; i < str.length(); i++) {
            char c = str.charAt(i);
            if (c != ' ' && c != '\t' && c != '\r' && c != '\n') {
                return false;
            }
        }
        return true;
    }

    /**
     * 判断对象是否不为空（空列表，空字符串，空map）
     *
     * @param object
     * @return
     */
    public static boolean notEmpty(Object object) {
        return !isEmpty(object);
    }

    /**
     * 将对象转换成字符串
     *
     * @param object
     * @return
     */
    public static String toString(Object object) {
        return object != null ? object.toString() : null;
    }

    /**
     * 判断所有参数都是空
     *
     * @param objects
     * @return
     */
    public static boolean isAllEmpty(Object... objects) {
        for (Object object : objects) {
            if (!isEmpty(object)) {
                return false;
            }
        }
        return true;
    }

    /**
     * 判断是否有任意一个参数是空
     *
     * @param objects
     * @return
     */
    public static boolean isAnyEmpty(Object... objects) {
        for (Object object : objects) {
            if (isEmpty(object)) {
                return true;
            }
        }
        return false;
    }

    /**
     * 将对象转换成map
     *
     * @param parameterObject 对象
     * @return
     */
    public static Map<String, Object> objectToMap(Object parameterObject) {
        return objectToMap(parameterObject, false);
    }

    /**
     * 将对象转换成map
     *
     * @param parameterObject 对象
     * @param ignoreNullValue 是否忽略空值
     * @return
     */
    public static Map<String, Object> objectToMap(Object parameterObject, boolean ignoreNullValue) {
        Map<String, Object> map = new LinkedHashMap<>();
        if (parameterObject == null) {
            return map;
        }
        Class<?> cls = parameterObject.getClass();
        while (cls != Object.class) {
            processMapFields(parameterObject, map, cls, ignoreNullValue);
            cls = cls.getSuperclass();
        }
        return map;
    }

    private static void processMapFields(Object parameterObject, Map<String, Object> map, Class<?> cls, boolean ignoreNullValue) {
        Field[] fields = cls.getDeclaredFields();
        for (Field field : fields) {
            int modifiers = field.getModifiers();
            if (modifiers != Modifier.PUBLIC && modifiers != Modifier.PRIVATE && modifiers != Modifier.PROTECTED) {
                //过滤掉static
                continue;
            }
            try {
                field.setAccessible(true);
                if (field.isAccessible()) {
                    Object value = field.get(parameterObject);

                    if (ignoreNullValue) {
                        if (value != null) {
                            map.put(field.getName(), value);
                        }
                    } else {
                        map.put(field.getName(), value);
                    }
                }
            } catch (IllegalAccessException e) {
                logger.error(e.getMessage(), e);
            }
        }
    }

    /**
     * 深度克隆一个对象
     *
     * @param object 克隆的对象，必须实现Serializable接口
     * @param <T>
     * @return
     */
    public static <T> T clone(T object) {
        try {
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            ObjectOutputStream oos = new ObjectOutputStream(baos);
            oos.writeObject(object);
            ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
            ObjectInputStream ois = new ObjectInputStream(bais);
            return (T) ois.readObject();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 获取包括父类所有的属性
     *
     * @param clazz
     * @return
     */
    public static List<Field> getAllFields(Class<?> clazz) {
        List<Field> fieldList = new ArrayList<>();
        Class tempClass = clazz;
        Field[] fields;
        while (tempClass != null && tempClass != Object.class) {
            fields = tempClass.getDeclaredFields();
            if (ObjectUtils.notEmpty(fields)) {
                for (Field field : fields) {
                    if (field.getModifiers() == Modifier.PRIVATE) {
                        fieldList.add(field);
                    }
                }
            }
            tempClass = tempClass.getSuperclass();
        }
        return fieldList;
    }
}
